#ifndef VRPROUTEGRAPH_H
#define VRPROUTEGRAPH_H

#include <boost/shared_ptr.hpp>
#include <qmapcontrol.h>

#include "VRPGraph.h"

typedef boost::shared_ptr<qmapcontrol::LineString> LineStringPtr;
typedef boost::shared_ptr<qmapcontrol::Point> CirclePointPtr;

/// Regestry new property for route graph vertex and edge:
enum vertex_coordinate_t {vertex_coordinate};
enum edge_route_t {edge_route};
namespace boost
{
    BOOST_INSTALL_PROPERTY(vertex, coordinate);
    BOOST_INSTALL_PROPERTY(edge, route);
}

class VRPRouteGraphTraits
{
private:
    /// Property for VRPRouteGraph vertex
    typedef boost::property<vertex_demand_t, std::size_t> VertexDemandPropertyPrivate;
    typedef boost::property<boost::vertex_name_t, std::string, VertexDemandPropertyPrivate> VertexNamePropertyPrivate;
    typedef boost::property<vertex_backhaul_t, bool, VertexNamePropertyPrivate> VertexBackhaulPropertyPrivate;
    typedef boost::property<vertex_coordinate_t, CirclePointPtr, VertexBackhaulPropertyPrivate> VertexCoordinatePropertyPrivate;
    /// Property for VRPRouteGraph edge
    typedef boost::property<edge_route_t, LineStringPtr> EdgeRoutePropertyPrivate;
    typedef boost::property<boost::edge_weight_t, std::size_t, EdgeRoutePropertyPrivate> EdgeWeightPropertyPrivate;

public:
    typedef boost::adjacency_list< boost::listS,
                                   boost::listS,
                                   boost::undirectedS,
                                   VertexCoordinatePropertyPrivate,
                                   EdgeWeightPropertyPrivate> Graph;

    typedef boost::graph_traits<Graph>::vertex_descriptor Vertex;
    typedef boost::graph_traits<Graph>::edge_descriptor Edge;

    typedef boost::property_map<Graph, vertex_demand_t>::type VertexDemandMap;
    typedef boost::property_map<Graph, boost::vertex_name_t>::type VertexNameMap;
    typedef boost::property_map<Graph, vertex_backhaul_t>::type VertexBackhaulMap;
    typedef boost::property_map<Graph, vertex_coordinate_t>::type VertexCoordinateMap;

    typedef boost::property_map<Graph, boost::edge_weight_t>::type EdgeWeightMap;
    typedef boost::property_map<Graph, edge_route_t>::type EdgeRouteMap;

    typedef boost::graph_traits<Graph>::vertex_iterator VertexIterator;
    typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator;

    static Vertex null_vertex()
    {
        return boost::graph_traits<Graph>::null_vertex();
    }

    static VertexBackhaulMap GetVertexBackhaulMap(Graph& graph)
    {
        return get(vertex_backhaul, graph);
    }

    static VertexNameMap GetVertexNameMap(Graph& graph)
    {
        return get(boost::vertex_name, graph);
    }

    static VertexCoordinateMap GetVertexCoordinateMap(Graph& graph)
    {
        return get(vertex_coordinate, graph);
    }

    static VertexDemandMap GetVertexDemandMap(Graph& graph)
    {
        return get(vertex_demand, graph);
    }

    static EdgeWeightMap GetEdgeWeightMap(Graph& graph)
    {
        return get(boost::edge_weight, graph);
    }

    static EdgeRouteMap GetEdgeRouteMap(Graph& graph)
    {
        return get(edge_route, graph);
    }

    static Vertex GetFirstVertex(Graph& graph)
    {
        std::pair<VertexIterator, VertexIterator> beginPair;
        beginPair = boost::vertices(graph);
        if(beginPair.first != beginPair.second)
            return *beginPair.first;
        else
            return null_vertex();
    }

};


#endif // VRPROUTEGRAPH_H
